﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Faust.Andrew.MTG.Player
{
	/// <summary>
	/// Interaction logic for PlayerSurface.xaml
	/// </summary>
	partial class PlayerSurface : UserControl
	{
        private Dictionary<int, Card> _cards;
        
        #region constructors
        static PlayerSurface()
        {
            PresenterProperty = DependencyProperty.Register("Presenter", typeof(GamePresenter), typeof(PlayerSurface));
            PlayerProperty = DependencyProperty.Register("Player", typeof(PlayerState), typeof(PlayerSurface), new PropertyMetadata(OnPlayerPropertyChanged));
        }

        public PlayerSurface(GamePresenter presenter, PlayerState player, PlaySurface parentSurface)
            : this()
        {
            Presenter = presenter;
            Player = player;
            _parentSurface = parentSurface;
        }


        public PlayerSurface()
        {
            _cards = new Dictionary<int, Card>();
            this.InitializeComponent();
        }
        #endregion

        private PlaySurface _parentSurface;
        public PlaySurface ParentSurface
        {
            get { return _parentSurface; }
            set { _parentSurface = value; }
        }

        static DependencyProperty PresenterProperty;
        public GamePresenter Presenter
        {
            get
            {
                return (GamePresenter)base.GetValue(PresenterProperty);
            }
            set
            {
                base.SetValue(PresenterProperty, value);
            }
        }

        static DependencyProperty PlayerProperty;
        public PlayerState Player
        {
            get
            {
                return (PlayerState)base.GetValue(PlayerProperty);
            }
            set
            {
                base.SetValue(PlayerProperty, value);
            }
        }

        //private void btnDeck_Click(object sender, System.Windows.RoutedEventArgs e)
        //{
        //    if (Player.PlayerID == Presenter.Model.CurrentPlayer.PlayerID)
        //    {
        //        DrawTarget target = DrawCardTarget.Prompt();
        //        if (target == DrawTarget.Hand)
        //        {
        //            Presenter.Model.DrawCard(true);
        //        }
        //        else if (target == DrawTarget.Workspace)
        //        {
        //            Presenter.Model.DrawCard(false);
        //        }
        //    }
        //}

        #region Card Addition/Deletion/Movement
        private static void OnPlayerPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PlayerSurface surface = d as PlayerSurface;
            surface.OnPlayerPropertyChanged();
        }

        protected void OnPlayerPropertyChanged()
        {
            Player.Cards.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Cards_CollectionChanged);
        }

        void Cards_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
            {
                foreach (Shared.GameCard card in e.NewItems)
                {
                    Card uiCard = new Card();
                    card.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(Card_PropertyChanged);
                    uiCard.DataContext = card;
                    uiCard.Presenter = Presenter;
                    _cards.Add(card.CardID, uiCard);
                    canvas.Children.Add(uiCard);
                    Canvas.SetTop(uiCard, card.Location.Y);
                    Canvas.SetLeft(uiCard, card.Location.X);
                    //uiCard.PreviewMouseLeftButtonDown += Card_InterceptMove;
                    uiCard.PreviewMouseLeftButtonDown += Card_UpdateZIndex;
                    //uiCard.PreviewMouseLeftButtonUp += Card_MouseUp;
                    uiCard.PreviewMouseDoubleClick += Card_PreviewDoubleClick;
                    uiCard.PreviewMouseLeftButtonDown += Card_PreviewLeftMouseButtonDown;
                    uiCard.PreviewMouseMove += Card_PreviewMouseMove;
                    uiCard.MouseEnter += Card_MouseEnter;  
                }
            }
            else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
            {
                foreach (Shared.GameCard card in e.OldItems)
                {
                    if (_cards.ContainsKey(card.CardID))
                    {
                        Card uiCard = _cards[card.CardID];
                        (uiCard.DataContext as Shared.GameCard).PropertyChanged -= Card_PropertyChanged;
                        
                        //uiCard.PreviewMouseLeftButtonUp -= Card_MouseUp;
                        //uiCard.PreviewMouseLeftButtonDown -= Card_InterceptMove;
                        uiCard.PreviewMouseLeftButtonDown -= Card_UpdateZIndex;
                        uiCard.MouseEnter -= Card_MouseEnter;
                        uiCard.PreviewMouseDoubleClick -= Card_PreviewDoubleClick;
                        uiCard.PreviewMouseLeftButtonDown -= Card_PreviewLeftMouseButtonDown;
                        uiCard.PreviewMouseMove -= Card_PreviewMouseMove;
                        uiCard.DataContext = null;
                        canvas.Children.Remove(uiCard);
                        _cards.Remove(card.CardID);
                    }
                }
            }
        }

        void Card_PreviewMouseMove(object sender, MouseEventArgs e)
        {            
            Presenter.PreviewMouseMove((FrameworkElement)sender, e, this);            
        }

        void Card_PreviewLeftMouseButtonDown(object sender, MouseButtonEventArgs e)
        {            
            Presenter.PreviewMouseLeftButtonDown((FrameworkElement)sender, e, true);
        }

        protected FrameworkElement GetRootElement()
        {
            FrameworkElement element = this;
            while (element.Parent is FrameworkElement)
            {
                element = (FrameworkElement)element.Parent;
            }

            return element;
        }

        void Card_PreviewDoubleClick(object sender, MouseButtonEventArgs e)
        {
            Shared.GameCard card = (sender as Card).DataContext as Shared.GameCard;
            Presenter.Model.ToggleTap(card);
        }

        void Card_MouseEnter(object sender, MouseEventArgs e)
        {
            //Presenter.PreviewCard(sender as FrameworkElement);
            Shared.GameCard card = (sender as Card).DataContext as Shared.GameCard;
            Presenter.PreviewCard(card);
        }

        void Card_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "ControllerID")
            {
                Shared.GameCard gameCard = sender as Shared.GameCard;
                if (gameCard != null)
                {
                    if (_cards.ContainsKey(gameCard.CardID))
                    {
                        Card uiCard = _cards[gameCard.CardID];
                        //uiCard.PreviewMouseLeftButtonUp -= Card_MouseUp;
                        uiCard.PreviewMouseLeftButtonDown -= Card_InterceptMove;
                        uiCard.PreviewMouseLeftButtonDown -= Card_UpdateZIndex;

                        if (gameCard.ControllerID == Player.PlayerID)
                        {
                            uiCard.PreviewMouseLeftButtonDown += Card_UpdateZIndex;
                            //uiCard.PreviewMouseLeftButtonUp += Card_MouseUp;
                        }
                        else
                        {
                            uiCard.PreviewMouseLeftButtonDown += Card_InterceptMove;
                        }
                    }
                }
            }
        }

        void Card_UpdateZIndex(object sender, MouseButtonEventArgs e)
        {
            Shared.GameCard card = (sender as Card).DataContext as Shared.GameCard;
            if (!Presenter.Model.CanMoveCard(card.CardID)) { return; }

            if (sender is Card && (sender as Card).DataContext is Shared.GameCard)
            {
                Faust.Andrew.MTG.Player.Shared.GameCard gameCard = ((sender as Card).DataContext as Shared.GameCard);
                double zMax = Presenter.Model.LargestZIndex(gameCard.Location.PlayerID);
                gameCard.Location.Z = zMax + 1;
            }                       
        }

        void Card_InterceptMove(object sender, MouseButtonEventArgs e)
        {
            Shared.GameCard card = (sender as Card).DataContext as Shared.GameCard;
            if (!Presenter.Model.CanMoveCard(card.CardID))
            {
                e.Handled = true;
            }
        }

        //void Card_MouseUp(object sender, MouseButtonEventArgs e)
        //{
        //    Shared.GameCard card = (sender as Card).DataContext as Shared.GameCard;
        //    if (!Presenter.Model.CanMoveCard(card.CardID)) { return; }

        //    if (sender is Card && (sender as Card).DataContext is Shared.GameCard)
        //    {
        //        /*FindPlayerUnderMouse();                    */
        //        Presenter.Model.MoveCard(((sender as Card).DataContext as Shared.GameCard));
        //    }
        //}

        private void Search_Deck(object sender, System.Windows.RoutedEventArgs e)
        {
            Presenter.ViewDeck(Player.PlayerID);
        }

        private void Shuffle_Deck(object sender, System.Windows.RoutedEventArgs e)
        {
            Presenter.Model.ShuffleDeck(Player.PlayerID);
        }

        private void Search_Graveyard(object sender, System.Windows.RoutedEventArgs e)
        {
            Presenter.ViewGraveyard(Player.PlayerID);
        }

        private void Draw_One(object sender, System.Windows.RoutedEventArgs e)
        {
            if (Player.PlayerID != Presenter.Model.CurrentPlayer.PlayerID) { return; }
             
            DrawTarget target = DrawCardTarget.Prompt();
            Draw(target, 1);
        }

        private void Draw_Seven(object sender, System.Windows.RoutedEventArgs e)
        {
            if (Player.PlayerID != Presenter.Model.CurrentPlayer.PlayerID) { return; }

            if (MessageBox.Show("Are you certain you wish to draw 7 cards?", "Draw Seven?", MessageBoxButton.YesNo) == MessageBoxResult.No) { return; }

            DrawTarget target = DrawCardTarget.Prompt();
            Draw(target, 7);
        }

        private void Draw(DrawTarget target, int count)
        {
            for (int i = 0; i < count; i++)
            {
                if (target == DrawTarget.Hand)
                {
                    Presenter.Model.DrawCard(true);
                }
                else if (target == DrawTarget.Workspace)
                {
                    Presenter.Model.DrawCard(false);
                }
            }
        }

        private void Draw_Multiple(object sender, System.Windows.RoutedEventArgs e)
        {
            if (Player.PlayerID != Presenter.Model.CurrentPlayer.PlayerID) { return; }

            string countString = InputBox.ShowInput("How many cards do you wish to draw?", "1");
            int count;
            if (!Int32.TryParse(countString, out count) && count > 0)
            {
                MessageBox.Show("Must enter a valid value which is greater than 0");
                return;
            }

            if (MessageBox.Show(String.Format("Are you certain you wish to draw {0} cards?", count), String.Format("Draw {0}?", count), MessageBoxButton.YesNo) == MessageBoxResult.No) { return; }

            DrawTarget target = DrawCardTarget.Prompt();

            Draw(target, count);
        } 

       #endregion
        #region Card Information

        public bool ContainsCard(int cardID)
        {
            return _cards.ContainsKey(cardID);
        }

        public System.Windows.Point MeasureCard(int cardID)
        {
            Point point = new Point();
            point.X = _cards[cardID].ActualWidth;
            point.Y = _cards[cardID].ActualHeight;
            return point;
        }

        private void UserControl_Drop(object sender, System.Windows.DragEventArgs e)
        {
            Presenter.DropOnPlayspace(e);
        }                    
        #endregion

        private void Graveyard_PreviewDrop(object sender, DragEventArgs e)
        {
            Presenter.DropOnGraveyard(e);
        }

        private void Deck_PreviewDrop(object sender, DragEventArgs e)
        {
            Presenter.DropOnDeck(e);
        }

        private void Deck_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            Presenter.Deck_PreviewMouseLeftButtonDown((FrameworkElement)sender, e, true);
        }

        private void Deck_PreviewMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            Presenter.Deck_PreviewMouseRightButtonDown((FrameworkElement)sender, e, true);
        }

        private void Deck_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            Presenter.PreviewMouseMove((FrameworkElement)sender, e, this);
        }
    }
}